package indi.zjh.dp.db;

import indi.zjh.dp.db.Configuration.MySQLConf;
import indi.zjh.dp.error.MySQLConnectionUseupException;
import indi.zjh.dp.vc.Version;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.mysql.jdbc.Connection;

public class SessionFactory {
	private static Logger logger = Logger.getLogger(SessionFactory.class);
	
	protected Configuration configuration;
	
	protected List<Session> sessions = new ArrayList<Session>();
	
	public SessionFactory() throws Exception
	{
		throw new Exception("Can not create SessionFactory by construnct method");
	}
	
	public SessionFactory(Configuration c)
	{
		this.configuration = c;
	}
	
	public Session createSession() throws SQLException, MySQLConnectionUseupException
	{
		// 不使用连接池
		int poolSize = this.configuration.getMySQLConf().poolSize;
		// 使用sqlite, 不用连接池
		if(!Configuration.isMysql())
		{
			Session session = new Session(this);
			return session;
		}
		if(poolSize == 0)
		{
			Session session = new Session(this);
			return session;
		}
		
		// 使用连接池, 还没有达到连接池最大连接数, 创建新的连接
		int c = this.sessions.size();
		if(c < poolSize)
		{
			Session session = new Session(this);
			session.occupy();
			this.sessions.add(session);
			return session;
		}
		
		synchronized(this)
		{
			int i;
			//boolean isTimeout = false;
			ArrayList<Session> timeoutSess = new ArrayList<Session>();
			for(i = 0; i < c; ++i)
			{
				if(!this.sessions.get(i).isBusy())
				{
					if(!this.sessions.get(i).occupy())
					{
						timeoutSess.add(this.sessions.get(i));
					}
					else
					{
						return this.sessions.get(i);
					}
				}
			}
			
			
			// 从连接池去除超时的连接
			int len = timeoutSess.size();
			for(int j = 0; j < len; ++j)
			{
				this.sessions.remove(timeoutSess.get(j));
			}
			
			// 有超时的连接, 重新获取一次
			if(len > 0)
				return this.createSession();
			
			if(i == c)
			{
				throw new MySQLConnectionUseupException();
			}
		}
		return null;
	}
	
	public Configuration getConfiguration()
	{
		return this.configuration;
	}
	
}
